/**
 * Software License, Version 1.0
 * 
 * Copyright 2003 The Trustees of Indiana University.  All rights reserved.
 * 
 *
 *Redistribution and use in source and binary forms, with or without 
 *modification, are permitted provided that the following conditions are met:
 *
 *1) All redistributions of source code must retain the above copyright notice,
 * the list of authors in the original source code, this list of conditions and
 * the disclaimer listed in this license;
 *2) All redistributions in binary form must reproduce the above copyright 
 * notice, this list of conditions and the disclaimer listed in this license in
 * the documentation and/or other materials provided with the distribution;
 *3) Any documentation included with all redistributions must include the 
 * following acknowledgement:
 *
 *"This product includes software developed by the Community Grids Lab. For 
 * further information contact the Community Grids Lab at 
 * http://communitygrids.iu.edu/."
 *
 * Alternatively, this acknowledgement may appear in the software itself, and 
 * wherever such third-party acknowledgments normally appear.
 * 
 *4) The name Indiana University or Community Grids Lab or NaradaBrokering, 
 * shall not be used to endorse or promote products derived from this software 
 * without prior written permission from Indiana University.  For written 
 * permission, please contact the Advanced Research and Technology Institute 
 * ("ARTI") at 351 West 10th Street, Indianapolis, Indiana 46202.
 *5) Products derived from this software may not be called NaradaBrokering, 
 * nor may Indiana University or Community Grids Lab or NaradaBrokering appear
 * in their name, without prior written permission of ARTI.
 * 
 *
 * Indiana University provides no reassurances that the source code provided 
 * does not infringe the patent or any other intellectual property rights of 
 * any other entity.  Indiana University disclaims any liability to any 
 * recipient for claims brought by any other entity based on infringement of 
 * intellectual property rights or otherwise.  
 *
 *LICENSEE UNDERSTANDS THAT SOFTWARE IS PROVIDED "AS IS" FOR WHICH NO 
 *WARRANTIES AS TO CAPABILITIES OR ACCURACY ARE MADE. INDIANA UNIVERSITY GIVES
 *NO WARRANTIES AND MAKES NO REPRESENTATION THAT SOFTWARE IS FREE OF 
 *INFRINGEMENT OF THIRD PARTY PATENT, COPYRIGHT, OR OTHER PROPRIETARY RIGHTS. 
 *INDIANA UNIVERSITY MAKES NO WARRANTIES THAT SOFTWARE IS FREE FROM "BUGS", 
 *"VIRUSES", "TROJAN HORSES", "TRAP DOORS", "WORMS", OR OTHER HARMFUL CODE.  
 *LICENSEE ASSUMES THE ENTIRE RISK AS TO THE PERFORMANCE OF SOFTWARE AND/OR 
 *ASSOCIATED MATERIALS, AND TO THE PERFORMANCE AND VALIDITY OF INFORMATION 
 *GENERATED USING SOFTWARE.
 */
package cgl.narada.matching.xpath;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;

import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.apache.xpath.XPathAPI;
import org.w3c.dom.Document;
import org.w3c.dom.traversal.NodeIterator;

import cgl.narada.protocol.Protocol;

public class XmlEvent {
  private int source;
  private int topicName;
  private Document document;
  private byte[] documentBytes;
  private String moduleName="XmlEvent: ";
  
  public XmlEvent(int source, Document document) {
    this.source = source;
    this.document = document;
    ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
    try {
      ObjectOutputStream dout = new ObjectOutputStream(baOutputStream);
      dout.writeObject(document);
    } catch (IOException ioe) {
      System.out.println(moduleName + "Error marshalling stream" + ioe);
    } /* end try-catch */
    documentBytes =  baOutputStream.toByteArray();
  }
  
  public XmlEvent(byte[] xmlEventBytes) {
    try {
      ByteArrayInputStream baInputStream = 
	new ByteArrayInputStream(xmlEventBytes);
      DataInputStream din = new DataInputStream(baInputStream);
      din.readByte(); /* Ignore since we already know what's it gonna be */
      source = din.readInt();
      documentBytes = new byte[din.readInt()];
      din.readFully(documentBytes);
      
    } catch(IOException ioe) {
      System.out.println(moduleName + "Error during unmarshalling " + ioe);
    }/* end try-catch */
    
    try {
      ByteArrayInputStream baInputStream = 
	new ByteArrayInputStream(documentBytes);
      ObjectInputStream din = new ObjectInputStream(baInputStream);
      document = (Document)din.readObject();
    } catch(IOException ioe) {
      System.out.println(moduleName + "Error during unmarshalling " + ioe);
    } catch (ClassNotFoundException exception) {
      System.out.println(moduleName + "De-Serialization failed " +  
			 exception + "\n");
    }/* end try-catch */
  }
  
  public Document getDocument() {
    return document;
  }

  public int getSource() {
    return source;
  }
  
  public byte[] getBytes() {
    if (document == null) {
      System.out.println(moduleName + 
			 "Topic/Document associated with xml packet is null");
    }

    ByteArrayOutputStream baOutputStream = new ByteArrayOutputStream();
    DataOutputStream dout = new DataOutputStream(baOutputStream);
    try {
      
      dout.writeByte(Protocol.NARADA_XML_EVENT);
      dout.writeInt(source);
      dout.writeInt(documentBytes.length);
      dout.write(documentBytes);
      dout.flush();
    } catch (IOException ioe) {
      System.out.println(moduleName + "Error marshalling stream" + ioe);
    } /* end try-catch */
    return baOutputStream.toByteArray();
  }

  public String toString() {
    try {
      Transformer serializer = 
	TransformerFactory.newInstance().newTransformer();
      serializer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
      NodeIterator nl = XPathAPI.selectNodeIterator(document, "//");
      serializer.transform(new DOMSource(nl.nextNode()), 
			   new StreamResult(System.out));
    } catch (Exception e) {
      System.out.println(moduleName + e);
    }
    //String stringRep = source + " " + document;
    return " hey";
  }
  
  public static void main(String[] args) {
    Query query = new Query();
    //Document doc1 = query.getDocumentFromFile("foo.xml");
    Document doc = query.getDocumentFromFile(args[0]);
    XmlEvent xmlEvent = new XmlEvent(1111, doc);
    System.out.println(xmlEvent);
    xmlEvent = new XmlEvent(xmlEvent.getBytes());
    System.out.println(xmlEvent);
    
  }
} 
